home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / cgazv4n2.zip / SHROUD.C < prev    next >
C/C++ Source or Header  |  1989-10-25  |  11KB  |  314 lines

  1. /******************************** SHROUD.C *********************************
  2.  * Program: shroud.c - A code shrouder
  3.  * Author: Philip J. Erdelsky
  4.  * Compilers: Turbo C 2.0, MSC 5.1
  5.  * Memory Models: any
  6.  * Compile time switches: NESTCOM - if defined, nested comments are ok
  7.  *
  8.  * Usage: (1) expects list of keywords that are not to be translated in
  9.  *            a file named "keywords".  This file contains one keyword
  10.  *            per line.  Blank lines and lines beginning with a
  11.  *            semi-colon are ignored.
  12.  *        (2) expects a file containing a list of files to be translated
  13.  *            in a file named "filelist".  Each line of "filelist" should
  14.  *            contain a pair of files names separated by white space:
  15.  *              infile1.c  outfile1.c
  16.  *              infile2.c  outfile2.c
  17.  *                  ...
  18.  *        (3) the table of symbol translations is written to stdout
  19.  *
  20.  * Date: Sep. 1989  May be used freely if authorship is acknowledged.
  21.  ***********************************************************************/
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27.  
  28. #define MAXLAB   31     /* max number of characters that are meaningful
  29.                            in a symbol's name */
  30.  
  31. #define MAXFS  64       /* max length of a file specification */
  32.  
  33. #if 0
  34. #define NESTCOM 0       /* define this to allow nested comments */
  35. #endif
  36.  
  37. /******** common data items **************/
  38.  
  39. /* the structure we use to store symbol names */
  40. typedef struct label_table_entry {
  41.     struct label_table_entry *next;
  42.     int number;       /* translate it to Lnumber */
  43.     char name[1];     /* name of symbol is here and in following bytes */
  44. } label;
  45.  
  46. static int current_char;     /* current source file character */
  47. static FILE *source_file;
  48. static FILE *destination_file;
  49. static int label_number = 1;
  50.  
  51. /********************** error handlers ***********************/
  52. void error_exit(s)
  53. char *s;
  54. {
  55.     fputs(s, stderr);
  56.     exit(1);
  57. }
  58.  
  59. void cant_open(s)
  60. char *s;
  61. {
  62.     fprintf(stderr, "Can't open %s\n", s);
  63.     exit(1);
  64. }
  65.  
  66. void unexpected_EOF()
  67. {
  68.     error_exit("Unexpected end of file");
  69. }
  70.  
  71. /********************** input/output *************************/
  72. int next_char()
  73. {
  74.     return (current_char = getc(source_file));
  75. }
  76.  
  77. int put_current_char_get_next()
  78. {
  79.     putc(current_char, destination_file);
  80.     return (next_char());
  81. }
  82.  
  83. /****************** string & comment scanners ****************/
  84. /* scan input until end of string delimited by terminator */
  85. void scan_string(int terminator)
  86. {
  87.     put_current_char_get_next();
  88.     while(1) {
  89.         if (current_char == terminator)
  90.             break;
  91.         if (current_char == '\\')
  92.             put_current_char_get_next();
  93.         put_current_char_get_next();
  94.     }
  95.     put_current_char_get_next();
  96. }
  97.  
  98. /* scan a comment, discarding its contents */
  99. void scan_comment()
  100. {
  101.     next_char();
  102.     while (current_char!=EOF) {
  103. #ifdef NESTCOM
  104.         if (current_char == '/') {
  105.             if (next_char() == '*')
  106.                 scan_comment();
  107.         }
  108.         else
  109. #endif
  110.             if (current_char == '*') {
  111.                 if (next_char() == '/') {
  112.                     next_char();
  113.                     return;
  114.                 }
  115.             }
  116.             else
  117.                 next_char();
  118.     }
  119.     unexpected_EOF();
  120. }
  121.  
  122. /********************** main routine *************************/
  123. void main()
  124. {
  125.     label *first_label = NULL;      /* list of translated symbols */
  126.     label *last_label;
  127.  
  128.     label *first_keyword = NULL;    /* list of symbols to leave alone */
  129.     label *last_keyword;
  130.  
  131.     label *keyword, *this_label;
  132.     int c, i;
  133.     FILE *fp;
  134.     char name_buf[MAXLAB+1];
  135.  
  136.     /**** read in list of keywords and library function names ****/
  137.     fp = fopen ("KEYWORDS", "r");
  138.     if (fp == NULL) 
  139.         error_exit("Can't open KEYWORDS file");
  140.  
  141.     while (( c = getc (fp)) != EOF) {
  142.  
  143.         /* skip blank lines */
  144.         if (c == '\n')
  145.             continue;
  146.  
  147.         /* skip ;xxx lines */
  148.         if (c == ';') {
  149.             while (c != '\n' && c != EOF)
  150.                 c=getc(fp);
  151.             continue;
  152.         }
  153.  
  154.         /* looks like a symbol */
  155.         i = 0;
  156.         do {
  157.             if (i < MAXLAB) 
  158.                 name_buf[i++] = c;
  159.         }
  160.         while ((c = getc (fp)) != '\n' && c != EOF);
  161.  
  162.         name_buf[i] = '\0';
  163.         if (( keyword=(label *) malloc (sizeof (label) + i) ) == NULL)
  164.             error_exit("Insufficient memory");
  165.         strcpy (keyword->name, name_buf);
  166.         if (first_keyword == NULL)
  167.             first_keyword = last_keyword = keyword;
  168.         else {
  169.             last_keyword->next = keyword;
  170.             last_keyword = keyword;
  171.         }
  172.         keyword->next = NULL;
  173.     }
  174.     fclose(fp);
  175.  
  176.     /**** open file list file, starting retrieving file names ****/
  177.     fp = fopen("FILELIST", "r");
  178.     if (fp == NULL) error_exit("Can't open FILELIST file");
  179.  
  180.     puts("/* symbol translations generated by shroud.exe for\n");
  181.     while ((c = getc(fp)) != EOF) {
  182.         static char first_specs[MAXFS+1];
  183.         static char second_specs[MAXFS+1];
  184.         i = 0;
  185.         while (!isspace(c)) {
  186.             if (c == '\n' || c == EOF)
  187.                 error_exit("Destination file specifications missing");
  188.             if (i<MAXFS) first_specs[i++] = c;
  189.             else error_exit("Source file specifications too long");
  190.             c = getc(fp);
  191.         }
  192.         first_specs[i] = 0;
  193.  
  194.         while(isspace(c))   /* skip intervening white space */
  195.             c = getc(fp);
  196.  
  197.         i = 0;
  198.         while (!isspace(c)) {
  199.             if (c == EOF)
  200.                 error_exit("Destination file specifications missing");
  201.             if (i < MAXFS) second_specs[i++] = c;
  202.             else error_exit("Destination file specifications too long");
  203.             c = getc(fp);
  204.         }
  205.         second_specs[i] = 0;
  206.  
  207.         /* now report the file names and open them */
  208.         printf("  %s -> %s\n", first_specs, second_specs);
  209.         if ((source_file = fopen (first_specs,"r")) == NULL)
  210.             cant_open(first_specs);
  211.         if ((destination_file = fopen (second_specs,"w")) == NULL)
  212.             cant_open(second_specs);
  213.  
  214.         /* start scanning */
  215.         next_char();
  216.  
  217.         while (current_char!=EOF) {
  218.             if (current_char == '/') {
  219.                 if (next_char() == '*') scan_comment();
  220.                 else putc ('/', destination_file);
  221.             }
  222.             else if (current_char == '\'' || current_char == '"') {
  223.                 scan_string(current_char);
  224.             }
  225.             else if (isdigit(current_char)) {
  226.                 do put_current_char_get_next();
  227.                 while (isalnum(current_char) || current_char == '.');
  228.             }
  229.             else if (isalpha(current_char) || current_char == '_') {
  230.                 i = 0;
  231.                 do {
  232.                     if (i<MAXLAB) name_buf[i++] = current_char;
  233.                     next_char();
  234.                 }
  235.                 while (isalpha(current_char) || current_char == '_');
  236.                 name_buf[i] = '\0';
  237.  
  238.                 /**** first, is this a keyword? ****/
  239.                 for (keyword = first_keyword; keyword != NULL; 
  240.                      keyword = keyword->next)
  241.                     if (strcmp(keyword->name, name_buf) == 0) break;
  242.                 if (keyword != NULL)
  243.                     fputs(name_buf, destination_file);
  244.  
  245.                 /**** not a keyword.  translate it ****/
  246.                 else {
  247.                     /* Is this label already known? */
  248.                     label *t;
  249.                     label *previous = NULL;
  250.                     for (t = first_label; t != NULL; t = t->next) {
  251.                         if (strcmp (t->name,name_buf) == 0)
  252.                             break;
  253.                         previous = t;
  254.                     }
  255.                     if (t == NULL)  /* If not, put it into the table */ {
  256.                         if (( this_label=(label *) malloc (sizeof(label) + i))
  257.                                         == NULL)
  258.                             error_exit("Insufficient memory");
  259.                         strcpy (this_label->name, name_buf);
  260.                         this_label->number = label_number++;
  261.                         if (first_label == NULL)
  262.                             first_label = last_label = this_label;
  263.                         else {
  264.                             last_label->next = this_label;
  265.                             last_label = this_label;
  266.                         }
  267.                         this_label->next = NULL;
  268.                         t = this_label;
  269.                     }
  270.                     else /* if so, move it to the beginning of the table */ {
  271.                         if (previous != NULL) {
  272.                             previous->next = t->next;
  273.                             t->next = first_label;
  274.                             first_label = t;
  275.                             if (last_label == t)
  276.                                 last_label = previous;
  277.                         }
  278.                     }
  279.                     fprintf (destination_file, "L%05d", t->number);
  280.                 }
  281.             }
  282.             else if (current_char == '\n') {
  283.                 put_current_char_get_next();
  284.                 while (current_char == ' ' || current_char == '\t')
  285.                        next_char();
  286.             }
  287.             else if (current_char == '#') {
  288.                 char cpp_directive[9];
  289.                 i = 0;
  290.                 put_current_char_get_next();
  291.                 while (isalpha(current_char)) {
  292.                     if ( i < 8)
  293.                        cpp_directive[i++] = current_char;
  294.                     put_current_char_get_next();
  295.                 }
  296.                 cpp_directive[i] = 0;
  297.                 /* we handle #include differently - musn't touch! */
  298.                 if (strcmp (cpp_directive, "include") == 0) {
  299.                     while (current_char != '\n' && current_char != EOF)
  300.                         put_current_char_get_next();
  301.                 }
  302.             }
  303.             else {
  304.                 put_current_char_get_next();
  305.             }
  306.         }
  307.     }
  308.  
  309.     /**** now write out translation table ****/
  310.     puts(" */");
  311.     putchar('\n');
  312.     for (keyword = first_label; keyword != NULL; keyword = keyword->next)
  313.         printf("#define L%05d %s\n", keyword->number, keyword->name);
  314. }